 

using System;
using System.Collections.Generic;
using System.Text;
using iTextSharp.text;
using System.IO;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;
using System.Collections;
using iTextSharp.text.html;
using System.Text.RegularExpressions;



#region HtmlToPdfBuilder Class

 
public class HtmlToPdfBuilder
{

    #region Constants

    private const string STYLE_DEFAULT_TYPE = "style";
    private const string DOCUMENT_HTML_START = "<html><head></head><body>";
    private const string DOCUMENT_HTML_END = "</body></html>";
    private const string REGEX_GROUP_SELECTOR = "selector";
    private const string REGEX_GROUP_STYLE = "style";


    private const string REGEX_GET_STYLES = @"(?<tablerow2>[^\{\s]+\w+(\s\[^\{\s]+)?)\s?\{(?<style>[^\}]*)\}";

    #endregion

    #region Constructors

   
    public HtmlToPdfBuilder(Rectangle size)
    {
        this.PageSize1 = size;
        this._Pages = new List<HtmlPdfPage>();
        this._Styles = new StyleSheet();
    }

    #endregion

    #region Delegates

    
    public event RenderEvent BeforeRender;

    
    public event RenderEvent AfterRender;

    #endregion

    #region Properties

    public Rectangle _PageSize1;
    
    public Rectangle PageSize1
    {
        get
        {
            return _PageSize1;
        }
        set
        {
            value = PageSize.LETTER;
        }
    }
     
    public HtmlPdfPage this[int index]
    {
        get
        {
            return this._Pages[index];
        }
    }

    
    public HtmlPdfPage[] Pages
    {
        get
        {
            return this._Pages.ToArray();
        }
    }

    #endregion

    #region Members

    private List<HtmlPdfPage> _Pages;
    private StyleSheet _Styles;

    #endregion

    #region Working With The Document

    
    public HtmlPdfPage AddPage()
    {
        HtmlPdfPage page = new HtmlPdfPage();
        this._Pages.Add(page);
        return page;
    }

    
    public void RemovePage(HtmlPdfPage page)
    {
        this._Pages.Remove(page);
    }

    
    public void AddStyle(string selector, string styles)
    {
        this._Styles.LoadTagStyle(selector, HtmlToPdfBuilder.STYLE_DEFAULT_TYPE, styles);
    }

     
    public void ImportStylesheet(string path)
    {



        string content = File.ReadAllText(path);

        
        foreach (Match match in Regex.Matches(content, HtmlToPdfBuilder.REGEX_GET_STYLES))
        {
            string selector = match.Groups[HtmlToPdfBuilder.REGEX_GROUP_SELECTOR].Value;

            string style = match.Groups[HtmlToPdfBuilder.REGEX_GROUP_STYLE].Value;
            if (selector == "body")
            {
                style = style.Replace("font-size: 11px;", "font-size: 8px;");
            }
            if (selector == "#user_content")
            {
                style = style.Replace("font-size: 13px;", "font-size: 8px;");
            }

            this.AddStyle(selector, style);
        }

        this.AddStyle("tablerow2", "background-color: #000000;" + "\r\n" + "border: 1px solid #4BB9F3;" + "\r\n" + "font-family: \"segoe ui,Arial,sans-serif\";" + "\r\n" + "font-size: 500px;" + "\r\n" + "line-height: 10px;" + "\r\n" + "color: #000000;" + "\r\n" + "text-decoration: none;" + "\r\n" + "padding: 2px;" + "\r\n" + "");

  
    }


    #endregion

    #region Document Navigation

    
    public void InsertBefore(HtmlPdfPage page, HtmlPdfPage before)
    {
        this._Pages.Remove(page);
        this._Pages.Insert(
            Math.Max(this._Pages.IndexOf(before), 0),
            page);
    }

    
    public void InsertAfter(HtmlPdfPage page, HtmlPdfPage after)
    {
        this._Pages.Remove(page);
        this._Pages.Insert(
            Math.Min(this._Pages.IndexOf(after) + 1, this._Pages.Count),
            page);
    }


    #endregion

    #region Rendering The Document

    
    public byte[] RenderPdf()
    {

         MemoryStream file = new MemoryStream();
        Document document = new Document(PageSize.LETTER);
        PdfWriter writer = PdfWriter.GetInstance(document, file);

         if (this.BeforeRender is RenderEvent)
        {
            this.BeforeRender(writer, document);
        }

         document.Open();

         foreach (HtmlPdfPage page in this._Pages)
        {
            document.NewPage();

             MemoryStream output = new MemoryStream();
            StreamWriter html = new StreamWriter(output, Encoding.UTF8);

             html.Write(string.Concat(HtmlToPdfBuilder.DOCUMENT_HTML_START, page._Html.ToString(), HtmlToPdfBuilder.DOCUMENT_HTML_END));
            html.Close();
            html.Dispose();

             MemoryStream generate = new MemoryStream(output.ToArray());
            StreamReader reader = new StreamReader(generate);
            foreach (object item in HTMLWorker.ParseToList(reader, this._Styles))
            {
                document.Add((IElement)item);
            }

             html.Dispose();
            reader.Dispose();
            output.Dispose();
            generate.Dispose();

        }

         if (this.AfterRender is RenderEvent)
        {
            this.AfterRender(writer, document);
        }

         document.Close();
        return file.ToArray();

    }

    #endregion

}

#endregion

#region HtmlPdfPage Class

 
public class HtmlPdfPage
{

    #region Constructors

    
    public HtmlPdfPage()
    {
        this._Html = new StringBuilder();
    }

    #endregion

    #region Fields

     internal StringBuilder _Html;

    #endregion

    #region Working With The Html

    
    public virtual void AppendHtml(string content, params object[] values)
    {
        this._Html.AppendFormat(content, values);
    }

    #endregion

}

#endregion

#region Rendering Delegate

 
public delegate void RenderEvent(PdfWriter writer, Document document);

#endregion


